#!/usr/bin/python

# Compares the absolute number of iterations of loops in a program against its guessed
# range. The input file shall following the pattern:
#  - Top level range guess: "first-guess: script=<script-filename>:<script-lineno> pc=<loop-pc> range=<range>"
#  - First nesting level range guess: "second-guess: script=<script-filename>:<script-lineno> pc=<loop-pc> range=<range>"
#  - Absolute ireration: "iteration script=<script-filename>:<script-lineno> pc=<loop-pc>"
#  - Script return: "return: script=<script-filename>:<script-lineno>"
#  - Script stop: "stop: script=<script-filename>:<script-lineno>" 
#
# Absolute iterations are accounted until the first return or stop instruction for the
# script.

import sys
import os

inputFile = open(sys.argv[1]);

# Extract the scripts' IDs in the input file.
scripts = set();

while True:
    line = inputFile.readline();
    if not line:
        break;
    if line.find("script=") != -1:
        script = line.split("script=")[-1];
        script = script.split(" ")[0];
        script = script.split("\n")[0];
        scripts.add(script);

scripts = list(scripts);

# Extract the IDs of the guessed loops (to reduce computation size).
scriptsLoopsDic = {};
absLoops = set();


for script in scripts:
    inputFile.seek(0);
    while True:
        line = inputFile.readline();
        if not line:
            break;
        if line.find("pc=") != -1 and line.find(script + " ") != -1:
            loop = line.split(" ", 1)[-1];
            pc = loop.split("pc=", 1)[-1];
            pc = pc.split(" ", 1)[0];
            pc = pc.split("\n", 1)[0];
            loop = loop.split(" pc=", 1)[0];
            loop += (" pc=" + pc);

            if script not in scriptsLoopsDic:
                scriptsLoopsDic[script] = set();

            if line.find("guess") != -1:
                scriptsLoopsDic[script].add(loop);

            absLoops.add(loop);

for script in scriptsLoopsDic:
    scriptsLoopsDic[script] = list(scriptsLoopsDic[script]);

# Extract the absolute results.
loopsResults = {};

for script in scriptsLoopsDic:
    for loop in scriptsLoopsDic[script]:
        inputFile.seek(0);
        while True:
            line = inputFile.readline();
            if not line:
                break;
            if (line.find("return") != -1 or line.find("stop") != -1) and (line.find(script + " ") != -1 or line.find(script + "\n") != -1):
                break;

            if (line.find(loop + " ") != -1 or line.find(loop + "\n") != -1) and line.find("iteration") != -1:
                if loop not in loopsResults:
                    loopsResults[loop] = 0;

                loopsResults[loop] += 1;

        if loop in loopsResults:
            loopsResults[loop] = {"absolute":loopsResults[loop]};
            loopsResults[loop]["script"] = script;

# Extract the guessed results for loops that are not nested.
for loop in loopsResults:
    inputFile.seek(0);
    while True:
        line = inputFile.readline();
        if not line:
            break;
        if (line.find(loop + " ") != -1 or line.find(loop + "\n") != -1) and line.find("first-guess") != -1:
            guess = line.split("range=")[-1];
            guess = guess.split("\n")[0];
            guess = guess.split(" ")[0];
            guess = int(guess);
            loopsResults[loop]["guessed"] = guess;

# Extract the guessed results for first nesting level loops.
for loop in loopsResults:
    inputFile.seek(0);
    while True:
        line = inputFile.readline();
        if not line:
            break;
        if (line.find(loop + " ") != -1 or line.find(loop + "\n") != -1) and line.find("second-guess") != -1:
            guess = line.split("range=")[-1];
            guess = guess.split("\n")[0];
            guess = guess.split(" ")[0];
            guess = int(guess);

            for in_loop in loopsResults:
                if in_loop.find(loopsResults[loop]["script"] + " ") != -1 and ("guessed" in loopsResults[in_loop]):
                    loopsResults[loop]["guessed"] = guess * loopsResults[in_loop]["guessed"];
                    break;

# Print the results.
print "GUESSED,ABSOLUTE";

for loop in loopsResults:
    if "guessed" in loopsResults[loop] and "absolute" in loopsResults[loop]:
        print str(loopsResults[loop]["guessed"]) + "," + str(loopsResults[loop]["absolute"]);

print ",\nNUMBER OF LOOPS IN THE PROGRAM:," + str(len(absLoops));
print "NUMBER OF GUESSED LOOPS:," + str(len(loopsResults));
